﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Xml;
using DiscoveryLogic.Analytics.BusinessLogic.Rules;
using DiscoveryLogic.Analytics.DataObjects;
using DiscoveryLogic.Analytics.DataObjects.Rules;
using DiscoveryLogic.Analytics.Modules.Clusters;
using DiscoveryLogic.Analytics.Modules.DataNavigation;
using DiscoveryLogic.Analytics.Modules.Entities;
using DiscoveryLogic.Analytics.Modules.Networks;
using DiscoveryLogic.Analytics.Modules.Props;
using DiscoveryLogic.Analytics.Modules.Tools;
using DiscoveryLogic.Analytics.UI.Common.Events;
using DiscoveryLogic.Common.Utilities;
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Modularity;
using Microsoft.Practices.Composite.UnityExtensions;
using Microsoft.Practices.Composite.Wpf.Events;

namespace DiscoveryLogic.Analytics.Studio
{
	internal class Bootstrapper : UnityBootstrapper
	{
	    private VisualStudioLikeShell _Shell;

		protected override DependencyObject CreateShell()
		{
			//OutlookLikeShell shell2 = new OutlookLikeShell();
			//shell2.Show();
            this.MergeRules();
            this.CopyImageFiles();
            _Shell = new VisualStudioLikeShell();
            _Shell.Show();

            this.SubscribeEntityDataSetEventHandlers();
            this.SubscribeNetworkEventHandlers();
            return _Shell;
		}

        //protected override void InitializeModules()
        //{
        //    //IModule entityNavigatorModule = this.Container.Resolve<EntityNavigatorModule>();
        //    //entityNavigatorModule.Initialize();

        //    IModule toolboxModule = this.Container.Resolve<ToolboxModule>();
        //    toolboxModule.Initialize();

        //    //IModule propGridModule = this.Container.Resolve<PropGridModule>();
        //    //propGridModule.Initialize();

        //    PersonListModule personListModule = this.Container.Resolve<PersonListModule>();
        //    personListModule.Initialize();

        //    PersonModule personModule = this.Container.Resolve<PersonModule>();
        //    personModule.Initialize();

        //    NetworkViewModule networkModule = this.Container.Resolve<NetworkViewModule>();
        //    networkModule.Initialize();

        //    GravityGraphModule gravityModule = this.Container.Resolve<GravityGraphModule>();
        //    gravityModule.Initialize();
        //}

        protected override IModuleEnumerator GetModuleEnumerator()
        {
            return new StaticModuleEnumerator()
                .AddModule(typeof(EntitySetsTreeModule))
                .AddModule(typeof(NetworkTreeModule))
                .AddModule(typeof(RuleTreeModule))
                //.AddModule(typeof(GrantListModule))
                //.AddModule(typeof(PersonListModule))
                //.AddModule(typeof(PubListModule))
                //.AddModule(typeof(OrgListModule))
                .AddModule(typeof(PersonModule))
                .AddModule(typeof(GrantModule))
                .AddModule(typeof(OrgModule))
                .AddModule(typeof(PubModule))
                //.AddModule(typeof(NetworkViewModule))
                //.AddModule(typeof(NetworkDataModule))
                //.AddModule(typeof(NetworkStatsModule))
                //.AddModule(typeof(GravityGraphModule))
                //.AddModule(typeof(RadialGraphModule))
                .AddModule(typeof(TagCloundModule));
            
        }

        #region entity set event handler
        private void SubscribeEntityDataSetEventHandlers()
        {
            IEventAggregator eventAggregator = this.Container.Resolve<IEventAggregator>();
            if (eventAggregator == null)
            {
                MessageBox.Show("Unable to resolve event aggregator");
                return;
            }

            GrantDataSetSelectedEvent grantSetSelectedEvent =
                eventAggregator.GetEvent<GrantDataSetSelectedEvent>();
            grantSetSelectedEvent.Subscribe(OnGrantSetSelected, ThreadOption.UIThread, true);

            OrgDataSetSelectedEvent orgDataSetSelectedEvent =
                eventAggregator.GetEvent<OrgDataSetSelectedEvent>();
            orgDataSetSelectedEvent.Subscribe(OnOrgSetSelected, ThreadOption.UIThread, true);

            PersonDataSetSelectedEvent personDataSetSelectedEvent =
                eventAggregator.GetEvent<PersonDataSetSelectedEvent>();
            personDataSetSelectedEvent.Subscribe(OnPersonSetSelected, ThreadOption.UIThread, true);

            PubDataSetSelectedEvent pubDataSetSelectedEvent =
                eventAggregator.GetEvent<PubDataSetSelectedEvent>();
            pubDataSetSelectedEvent.Subscribe(OnPubSetSelected, ThreadOption.UIThread, true);

            DocDataSetSelectedEvent docDataSetSelectedEvent =
                eventAggregator.GetEvent<DocDataSetSelectedEvent>();
            docDataSetSelectedEvent.Subscribe(OnDocSetSelected, ThreadOption.UIThread, true);

            SubjDataSetSelectedEvent subjDataSetSelectedEvent =
                eventAggregator.GetEvent<SubjDataSetSelectedEvent>();
            subjDataSetSelectedEvent.Subscribe(OnSubjSetSelected, ThreadOption.UIThread, true);
        }

        private void OnGrantSetSelected(string setName)
        {
            _Shell.HandlesEntitySetEventHandlers(EntityType.Grants,setName);
        }

        private void OnOrgSetSelected(string setName)
        {
            _Shell.HandlesEntitySetEventHandlers(EntityType.Organizations, setName);
        }

        private void OnPersonSetSelected(string setName)
        {
            _Shell.HandlesEntitySetEventHandlers(EntityType.Persons, setName);
        }

        private void OnPubSetSelected(string setName)
        {
            _Shell.HandlesEntitySetEventHandlers(EntityType.Publications, setName);
        }

        private void OnDocSetSelected(string setName)
        {
            _Shell.HandlesEntitySetEventHandlers(EntityType.Document, setName);
        }

        private void OnSubjSetSelected(string setName)
        {
            _Shell.HandlesEntitySetEventHandlers(EntityType.Subject, setName);
        }
        #endregion

        #region network event handler 
        private void SubscribeNetworkEventHandlers()
        {
            IEventAggregator eventAggregator = this.Container.Resolve<IEventAggregator>();
            if (eventAggregator == null)
            {
                MessageBox.Show("Unable to resolve event aggregator");
                return;
            }

            ViewNetworkDataEvent viewNetworkDataEvent =
                eventAggregator.GetEvent<ViewNetworkDataEvent>();
            viewNetworkDataEvent.Subscribe(
                _Shell.OnViewNetworkData, ThreadOption.UIThread, true);

            ViewNetworkGraphEvent viewNetworkGraphEvent =
                eventAggregator.GetEvent<ViewNetworkGraphEvent>();
            viewNetworkGraphEvent.Subscribe(
                _Shell.OnViewNetworkGraph, ThreadOption.UIThread, true);

            ViewNetworkStatsEvent viewNetworkStatsEvent =
                eventAggregator.GetEvent<ViewNetworkStatsEvent>();
            viewNetworkStatsEvent.Subscribe(
                _Shell.OnViewNetworkStats, ThreadOption.UIThread, true);
        }
        #endregion

        #region sample data
        private void MergeRules()
        {
            string appFolderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            if (appFolderPath.ToLower().EndsWith("\\debug"))
                appFolderPath = appFolderPath.Substring(0, appFolderPath.LastIndexOf("\\"));
            if (appFolderPath.ToLower().EndsWith("\\release"))
                appFolderPath = appFolderPath.Substring(0, appFolderPath.LastIndexOf("\\"));
            if (appFolderPath.ToLower().EndsWith("\\bin"))
                appFolderPath = appFolderPath.Substring(0, appFolderPath.LastIndexOf("\\"));
            string ruleFilePath2 = appFolderPath + "\\sampledata\\rules.rule";

            XmlDocument xDoc2 = new XmlDocument();
            xDoc2.Load(ruleFilePath2);
            XmlNodeList ruleNodes2 = xDoc2.DocumentElement.SelectNodes("Rule");
            Dictionary<string, RuleBase> rules2 = new Dictionary<string, RuleBase>();
            foreach (XmlNode ruleNode in ruleNodes2)
            {
                RuleType ruleType =
                    (RuleType) Enum.Parse(
                                   typeof (RuleType),
                                   XmlDataUtil.GetAttributeValue(
                                       ruleNode, "RuleType", RuleType.Import.ToString()));
                RuleBase rule = null;
                switch (ruleType)
                {
                    case RuleType.Import:
                        rule =
                            new EntityImportRule(string.Empty, SetDataSourceType.ExcelFile,
                                                 EntityType.Grants, string.Empty);
                        rule = (EntityImportRule) rule.Read(ruleNode);
                        break;
                    case RuleType.Link:
                        rule =
                            new EntityRelationRule(string.Empty, string.Empty,
                                                   EntityType.Grants, EntityType.Publications, string.Empty);
                        rule = (EntityRelationRule) rule.Read(ruleNode);
                        break;
                    case RuleType.Dedup:
                        rule =
                            new EntityDedupRule(string.Empty, RuleType.Dedup, SetDataSourceType.XML,
                                                EntityType.Publications, EntityType.Publications,
                                                EntityIcons.DedupRuleIcon);
                        rule = (EntityDedupRule) rule.Read(ruleNode);
                        break;
                    case RuleType.Cluster:
                        rule =
                            new EntityClusterRule(string.Empty, SetDataSourceType.XML, EntityType.Document);
                        rule = (EntityClusterRule) rule.Read(ruleNode);
                        break;
                    default:
                        break;
                }
                if (rule != null && !rules2.ContainsKey(rule.RuleName))
                    rules2.Add(rule.RuleName, rule);
            }
            string tgtFolderPath = DataFolder.NetworkDataFolder;
            string ruleFilePath1 = Path.Combine(tgtFolderPath, "Rules.rule");
            if (File.Exists(ruleFilePath1))
            {
                XmlDocument xDoc1 = new XmlDocument();
                xDoc1.Load(ruleFilePath1);
                XmlNodeList ruleNodes1 = xDoc1.DocumentElement.SelectNodes("Rule");
                List<string> ruleNames1 = new List<string>();
                foreach (XmlNode ruleNode in ruleNodes1)
                {
                    string ruleName = XmlDataUtil.GetAttributeValue(ruleNode, "RuleName", "");
                    if (!ruleNames1.Contains(ruleName))
                        ruleNames1.Add(ruleName);
                }
                foreach (string ruleName in rules2.Keys)
                {
                    if (!ruleNames1.Contains(ruleName))
                    {
                        XmlNode newRuleNode = XmlDataUtil.AddElement(ref xDoc1, xDoc1.DocumentElement, "Rule");
                        rules2[ruleName].Save(ref xDoc1, newRuleNode);
                    }
                }
                xDoc1.Save(ruleFilePath1);
            }
            else
            {
                File.Copy(ruleFilePath2, ruleFilePath1);
            }
        }

	    private void CopyImageFiles()
        {
            string tgtFolderPath = DataFolder.NetworkDataFolder;
            if (!Directory.Exists(tgtFolderPath))
                Directory.CreateDirectory(tgtFolderPath);
            string imgFolderPath = Path.Combine(tgtFolderPath, "images");

            if (!Directory.Exists(imgFolderPath))
            {
                Directory.CreateDirectory(imgFolderPath);

                string binFolderPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
                if (binFolderPath.ToLower().EndsWith("\\release"))
                    binFolderPath = binFolderPath.Substring(0, binFolderPath.LastIndexOf("\\"));
                if (binFolderPath.ToLower().EndsWith("\\debug"))
                    binFolderPath = binFolderPath.Substring(0, binFolderPath.LastIndexOf("\\"));
                if (binFolderPath.ToLower().EndsWith("\\bin"))
                    binFolderPath = binFolderPath.Substring(0, binFolderPath.LastIndexOf("\\"));
                string srcFolderPath = Path.Combine(binFolderPath, "images");
                DirectoryInfo dirInfo = new DirectoryInfo(srcFolderPath);
                FileInfo[] srcFiles = dirInfo.GetFiles();
                foreach (FileInfo srcFile in srcFiles)
                {
                    string tgtFilePath = Path.Combine(imgFolderPath, srcFile.Name);
                    srcFile.CopyTo(tgtFilePath, true);
                }
            }
        }
        #endregion
    }
}
